package com.heima.config.security.config;

import com.heima.config.security.filter.AuthFilter;
import com.heima.config.security.handler.MyAccessDeniedHandler;
import com.heima.config.security.entryPoint.MyAuthenticationEntryPoint;
import com.heima.config.security.service.UserDetailsCustomService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Autowired
    MyAccessDeniedHandler myAccessDeniedHandler;
    @Autowired
    MyAuthenticationEntryPoint myAuthenticationEntryPoint;
    @Autowired
    AuthFilter authFilter;

    // 用户详情service
    @Bean
    public UserDetailsService userDetailsService() {
        return new UserDetailsCustomService();
    }

    //
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.csrf(
                csrfConfigurer ->
                        csrfConfigurer.disable()
                )
                .authorizeHttpRequests(
                        auth ->
                                auth
                                        .anyRequest().authenticated()
                )
                .sessionManagement(
                        sessionManager ->
                                sessionManager
                                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                ) // 不再管理session
                .authorizeRequests().anyRequest().authenticated() // 除了所有允许匿名访问的接口外，任何其他接口都得先认证
                .and()
                .exceptionHandling(handling -> {
                    handling
                            .accessDeniedHandler(myAccessDeniedHandler) // 访问被拒绝的处理器
                            .authenticationEntryPoint(myAuthenticationEntryPoint); // 认证失败的处理入口
                });
        // 设置用户访问前filter
        http.addFilterBefore(authFilter, UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }

    @Bean
    public AuthenticationManager authenticationManager(
            UserDetailsService userDetailsService,
            PasswordEncoder passwordEncoder) {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(userDetailsService);
        authenticationProvider.setPasswordEncoder(passwordEncoder);
        ProviderManager providerManager = new ProviderManager(authenticationProvider);
        providerManager.setEraseCredentialsAfterAuthentication(false);

        return providerManager;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }
}